package org.hagen.mmia.yars.agent;

import java.io.IOException;
import java.util.ArrayList;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.util.Version;
import org.hagen.mmia.yars.client.User;
import org.hagen.mmia.yars.engine.Index;

public class Query {

	protected ArrayList<String> terms = null;
	protected IndexReader reader = null;
	protected ResultList lr = null;

	protected int hitsPerPage = 10;
	protected int totalHits = 0;

	/*
	 *  destructor
	 */
	public void destruct() {

		reader = null;
		hitsPerPage = 0;

		terms.clear();
		terms = null;
		
		lr.destruct();
		lr = null;
		
	}

	/*
	 *  constructor
	 */
	public Query(IndexReader reader ) {
		
		this.reader = reader;

		this.hitsPerPage = User.MAX_DOCS_PER_QUERY;

		terms = new ArrayList<String>();
		lr = new ResultList();
	}

	/*
	 * query terms
	 */
	public void addTerm(String term) {
		terms.add(term);
	}

	public void addTerms(ArrayList<String> terms ) {
		
		for( String t : terms ) {
			
			this.terms.add( t );
		}
	}
	
	public void addTerms(String[] initialQuery) {
		
		for( int i=0; i<initialQuery.length; i++)
			this.terms.add( initialQuery[i] );
	}	
	
	public ResultList getResultList() {
		return lr;
	}
	
	public int getTotalHits() {
		return totalHits;
	}
	
	/*
	 * execute query
	 */
	public void execute() throws ParseException, IOException {

		org.apache.lucene.search.Query query = buildQuery();

		// execute query
		TopScoreDocCollector collector = TopScoreDocCollector.create(
				this.hitsPerPage, true);
		
		IndexSearcher searcher = new IndexSearcher(reader);

		searcher.search(query, collector);

		totalHits = collector.getTotalHits();

		// store results
		storeRetrievedResuls( collector, searcher );
	}

	protected org.apache.lucene.search.Query buildQuery( ) throws ParseException {

		String queryString = null;
		
		// build query string
		for (String term : terms) {
			if (queryString == null) {
				queryString = new String(term);
			} else {
				queryString = queryString + " " + term;
			}
		}
		
		// parse query string
		return new QueryParser(Version.LUCENE_4_9, Index.FIELD_CONTENT, Index.analyzer)
				.parse(queryString);
	}
	
	protected void storeRetrievedResuls( TopScoreDocCollector collector, IndexSearcher searcher ) throws IOException {
		// store results
		ScoreDoc[] hits = collector.topDocs().scoreDocs;
		
		for (int i = 0; i < hits.length; ++i) {

			int  docId = hits[i].doc;
			Document d = searcher.doc(docId);
			String  ID = d.get( Index.FIELD_ID);

			lr.addRetrieved( ID );
		}
	}
	
	public void print() {
		System.out.print( "query terms: ");
		for( String term : terms ) {
			System.out.print( term  + " " );
		}
		System.out.println();
	}	
}
